//#include"glad/glad.h"
#include"mgepch.h"

#include "WindowsWindow.h"

#include"myMiniEngine/Platform/OpenGL/OpenGLContext.h"



namespace myMiniEngine {
	static bool isGLFWinit = false;
	static void GLFWErrorCallback(int error, const char* description)
	{
		MGE_CORE_ERROR("GLFW Error ({0}): {1}", error, description);
	}

	Window* Window::Create(const WindowProps& props)
	{
		return new WindowsWindow(props);
	}

	WindowsWindow::WindowsWindow(const WindowProps& props)
	{
		Init(props);
	}

	WindowsWindow::~WindowsWindow()
	{
		Shutdown();
	}


	void WindowsWindow::Init(const WindowProps& props)
	{
		data.Title = props.Titile;
		data.Width = props.Width;
		data.Height = props.Height;

		MGE_CORE_INFO("Creating Window {0}:({1},{2})", props.Titile, props.Width, props.Height);

		if (!isGLFWinit) {
			int flag = glfwInit();
			MGE_CORE_ASSERT(flag, "GLFW init failed!");
			glfwSetErrorCallback(GLFWErrorCallback);
			isGLFWinit = true;
		}

		window = glfwCreateWindow((int)props.Width, (int)props.Height, data.Title.c_str(), nullptr, nullptr);

		context = new OpenGLContext(window);
		context->Init();

		
		glfwSetWindowUserPointer(window, &data);
		SetVSync(true);

		
		/*glfwSetWindowFocusCallback(window, [](GLFWwindow* win, int focused) {
			if (focused) ImGui::SetCurrentContext((ImGuiContext*)glfwGetWindowUserPointer(win));
			});*/

		//glfw callbcaks
		glfwSetWindowSizeCallback(window, [](GLFWwindow* window, int width, int height) {
			WindowData& dat=*(WindowData*)glfwGetWindowUserPointer(window);
			dat.Width = width;
			dat.Height = height;
			WindowResizeEvent event(width, height);
			dat.EventCallback(event);
			});

		glfwSetWindowCloseCallback(window, [](GLFWwindow* window)
			{
				WindowData& data = *(WindowData*)glfwGetWindowUserPointer(window);
				WindowCloseEvent event;
				data.EventCallback(event);
			});

		glfwSetKeyCallback(window, [](GLFWwindow* window,int key,int scancode,int action,int mods) {
			WindowData& dat = *(WindowData*)glfwGetWindowUserPointer(window);
			switch (action)
			{
			case GLFW_PRESS:
			{
				KeyPressedEvent event(key, 0);
				dat.EventCallback(event);
				break;
			}
			case GLFW_RELEASE:
			{
				KeyReleasedEvent event(key);
				dat.EventCallback(event);
				break;
			}
			case GLFW_REPEAT:
			{
				KeyPressedEvent event(key, 1);
				dat.EventCallback(event);
				break;
			}
			}
			});

		glfwSetCharCallback(window, [](GLFWwindow* window, unsigned int keycode) {
			WindowData& dat = *(WindowData*)glfwGetWindowUserPointer(window);
			KeyTypedEvent event(keycode);
			dat.EventCallback(event);
			});

		glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mods)
			{
				WindowData& dat = *(WindowData*)glfwGetWindowUserPointer(window);

				switch (action)
				{
				case GLFW_PRESS:
				{
					MouseButtonPressedEvent event(button);
					dat.EventCallback(event);
					break;
				}
				case GLFW_RELEASE:
				{
					MouseButtonReleasedEvent event(button);
					dat.EventCallback(event);
					break;
				}
				}
			});

		glfwSetScrollCallback(window, [](GLFWwindow* window, double offx, double offy) {
			WindowData& dat = *(WindowData*)glfwGetWindowUserPointer(window);
			MouseScrolledEvent event((float)offx, (float)offy);
			dat.EventCallback(event);
			});
		glfwSetCursorPosCallback(window, [](GLFWwindow* window, double x, double y) {
			WindowData& dat = *(WindowData*)glfwGetWindowUserPointer(window);
			MouseMovedEvent event((float)x, (float)y);
			dat.EventCallback(event);
			});
	}

	void WindowsWindow::Shutdown()
	{
		glfwDestroyWindow(window);
	}

	void WindowsWindow::OnUpdate()
	{
		glfwPollEvents();
		context->SwapBuffer();
		
	}

	void WindowsWindow::SetVSync(bool enabled)
	{
		if (enabled) {
			glfwSwapInterval(1);
		}
		else {
			glfwSwapInterval(0);
		}
		data.VSync = enabled;
	}

	bool WindowsWindow::IsVSync() const
	{
		return data.VSync;
	}



}

